\documentclass[12pt]{article}
\usepackage{amsmath,amsthm,amssymb}
\usepackage{times}
\usepackage{verbatim}

\newtheorem{defn}{Definition}
\newtheorem{lem}{Lemma}
\newtheorem{thm}{Theorem}

\begin{document}
\section*{Low Memory}
\paragraph{}
If you look at low memory starting from \verb=0x0=, you will notice several
words containing instructions; essentially, it is an implementation of a
jump table in hardware. Many of these low memory locations contain the same
instruction: \verb=ldr pc, pc+18=; each one is signaled on a different
exception/interrupt condition. One of these conditions, a Fetch Abort, is 
generated when you try to access a memory location that doesn't exist. If you
install a Fetch Abort handler that itself generates a Fetch Abort, you have
a very nasty infinite loop.
\paragraph{}
Point being: just putting a value into a register \textit{can} cause
incredibly strange behaviour.
\section*{Kernel, revisited}
\begin{verbatim}
initialize();
FOREVER {
  schedule();
  activate();
  handle();
}
\end{verbatim}
\paragraph{}
As discussed, \verb=activate()= points to an \verb=entry= point. The entry
point will look like:
\begin{verbatim}
        movs  pc, lr
entry:  # rest of code...
        # store registers
        # load other registers
\end{verbatim}
\paragraph{}
Note the 's' at the end of \verb=movs= instruction; this 's' means
that the instruction also performs \( spsr \rightarrow cpsr \), unlike the
regular \verb=mov= instruction. In particular: it undoes the magic performed
by \verb=swi=.
\paragraph{}
We want to treat software and hardware interrupts in the same way, which
means that the kernel must be responsible for storing and restoring user
program state - the user program has no way to know when it will receive
a hardware interrupt, and so cannot handle this case.
\paragraph{}
To store and restore this state, we do:
\begin{verbatim}
                                    # we are in supervisor mode
        stmdb   sp!, {..., lr}      # store kernel state
        msr     cpsr_c, system      # switch to system mode
        ldr     sp, [td->sp]        # load stack pointer from task descriptor
        ldmia   sp!, {r0-ip, lr}    # restore new task state
        movs    pc, lr              # here, we enter user mode again
entry:  stmdb   sp!, {r0-ip, lr}    # store old task state
                                    # change to system mode
        str     sp, [td->sp]        # store stack pointer to task descriptor
                                    # change supervisor mode
        ldmia   sp! {..., lr}       # restore kernel state
\end{verbatim}
\paragraph{}
The important detail is this: user and supervisor mode have separate stacks.
We must switch modes at various points to ensure that we are manipulating the
correct stack pointer. There are a few details that have been left
unexplained:
\begin{itemize}
\item task arguments
\item return values
\end{itemize}
\paragraph{}
The context switch as shown deals with neither of these. Note that the user
and supervisor mode share some registers (r0-r7) and have separate copies of
others (sp, among others). The various interrupt modes have separate registers
as well; we will not concern ourselves with those until we cover interrupts.

\section*{Kernel Assignment, Part 1}
\paragraph{}
You will implement the following:
\begin{itemize}
\item \verb=Create()=: create a new task within the kernel
\item \verb=MyParentTid()=: return the task ID of the task that started me
\item \verb=MyTid()=: return my task ID
\item \verb=Pass()=: yield the CPU to the kernel, which may start another
task
\item \verb=Exit()=: stop my execution and remove me from any priority queues
\end{itemize}
\paragraph{}
You will also create a single task (the master/init/etc. task) which then
forks six sub-tasks at two different priorities, each of which perform the
following:
\begin{verbatim}
int main() {
  FOREVER {
    printf( COM2, "%d\r\n", MyTid() );
    Pass();
  }
}
\end{verbatim}

\end{document}
